package com.ashlikun.okhttputils.http.extend

import com.ashlikun.okhttputils.http.HttpUtils.UTF_8
import com.ashlikun.okhttputils.http.HttpUtils.getUrlFileName
import com.ashlikun.okhttputils.http.HttpUtils.isByteArray
import com.ashlikun.okhttputils.http.HttpUtils.launch
import com.ashlikun.okhttputils.http.OkHttpManage
import com.ashlikun.okhttputils.http.cache.CacheEntity
import com.ashlikun.okhttputils.http.convert.FileConvert
import com.ashlikun.okhttputils.http.response.HttpErrorCode
import com.ashlikun.okhttputils.http.response.IHttpResponse
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import okhttp3.Response
import okhttp3.ResponseBody
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.IOException
import java.io.UnsupportedEncodingException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.net.URLDecoder
import java.nio.charset.Charset

/**
 * 作者　　: 李坤
 * 创建时间: 2024/10/31　15:47
 * 邮箱　　：496546144@qq.com
 *
 * 功能介绍：
 */

/**
 * 打印返回消息
 */
fun Response.getResponseToString(): String {
    val sb = StringBuilder()
    sb.append("Heads : \n")
    sb.append(headers.toStringNoSensitive())
    val responseBody = body
    if (responseBody != null) {
        try {
            val contentLength = responseBody.contentLength()
            val source = responseBody.source()
            try {
                source.request(Long.MAX_VALUE)
            } catch (e: IOException) {
                e.printStackTrace()
            }
            val buffer = source.buffer()
            var charset = responseBody.contentType()?.charset() ?: Charset.forName("utf-8")
            val contentType = responseBody.contentType()
            if (contentType != null) {
                charset = contentType.charset(Charset.forName("utf-8"))
            }
            if (contentLength != 0L) {
                sb.append("\n")
                sb.append(buffer.clone().readString(charset))
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    return sb.toString()
}

/**
 * 根据响应头或者url获取文件名
 */
fun Response.getNetFileName(url: String): String {
    val response = this
    var fileName = if (response != null) response.getHeaderFileName() else ""
    if (fileName.isEmpty()) {
        fileName = getUrlFileName(url)
    }
    if (fileName.isEmpty()) {
        fileName = "unknownfile_" + System.currentTimeMillis()
    }
    try {
        fileName = URLDecoder.decode(fileName, "UTF-8")
    } catch (e: UnsupportedEncodingException) {
    }
    return fileName!!
}


/**
 * 解析文件头
 * Content-Disposition:attachment;filename=FileName.txt
 * Content-Disposition: attachment; filename*="UTF-8''%E6%9B%BF%E6%8D%A2%E5%AE%9E%E9%AA%8C%E6%8A%A5%E5%91%8A.pdf"
 */
fun Response.getHeaderFileName(): String {
    var dispositionHeader = header("Content-Disposition")
    if (dispositionHeader != null) {
        //文件名可能包含双引号，需要去除
        dispositionHeader = dispositionHeader.replace("\"".toRegex(), "")
        var split = "filename="
        var indexOf = dispositionHeader.indexOf(split)
        if (indexOf != -1) {
            return dispositionHeader.substring(indexOf + split.length, dispositionHeader.length)
        }
        split = "filename*="
        indexOf = dispositionHeader.indexOf(split)
        if (indexOf != -1) {
            var fileName = dispositionHeader.substring(indexOf + split.length, dispositionHeader.length)
            val encode = "UTF-8''"
            if (fileName.startsWith(encode)) {
                fileName = fileName.substring(encode.length, fileName.length)
            }
            return fileName
        }
    }
    return ""
}

/**
 * 从Response 里面把body内容克隆出来，保证Response的body还可以继续使用
 */
fun Response.getResponseCloneBody(): String {
    runCatching {
        if (isSuccessful) {
            val source = body?.source()
            if (source != null) {
                source.request(Long.MAX_VALUE)
                val buffer = source.buffer
                val contentType = body!!.contentType()
                val charset = if (contentType != null) contentType.charset(UTF_8) else UTF_8
                return buffer.clone().readString(charset!!)
            }
        }
    }
    return ""
}

/**
 * 处理返回值
 */
@Throws(IOException::class)
fun <T> Response.handlerResult(type: Type, gson: Gson): T {
    val response = this
    return if (type === Response::class.java) {
        response as T
    } else if (type === ResponseBody::class.java) {
        response.body as T
    } else if (type == File::class.java) {
        FileConvert(OkHttpManage.app!!.cacheDir.path).convertResponse(response, gson) as T
    } else if (isByteArray(type)) {
        val byteArray = response.body?.byteStream()?.use { input ->
            val byteArrayOutputStream = ByteArrayOutputStream()
            input.copyTo(byteArrayOutputStream)
            byteArrayOutputStream.toByteArray()
        } ?: byteArrayOf()
        byteArray as T
    } else {
        response.handlerResult(type, response.body?.string() ?: "", gson) as T
    }
}


/**
 * 处理返回值,只解析String或者自定义类型
 */
@Throws(IOException::class)
fun <T> Response.handlerResult(type: Type, json: String, gson: Gson): T {
    val response = this
    return if (type === String::class.java) json as T
    else {
        var res: T? = null
        runCatching {
            if (json.isEmpty()) throw JsonSyntaxException("json length = 0")
            runCatching {
                var cls = if (type is Class<*>) type
                else (type as? ParameterizedType)?.rawType as? Class<*>
                if (cls != null) {
                    if (IHttpResponse::class.java.isAssignableFrom(cls)) {
                        res = (cls.newInstance() as IHttpResponse).parseData(gson, json, type, response)
                    }
                }
            }.onFailure { it.printStackTrace() }
            res = res ?: gson.fromJson(json, type)
        }.onFailure { e ->
            //数据解析异常，统一回调错误,运行到新的线程不占用当前线程
            launch {
                OkHttpManage.onDataParseError?.invoke(HttpErrorCode.HTTP_DATA_ERROR, e, response, json)
            }
            throw IOException("${HttpErrorCode.MSG_DATA_ERROR2} \n  原异常：$e  \n json = $json")
        }
        res.also {
            if (it is IHttpResponse) {
                it.json = json
                it.httpCode = response.code
                it.response = response
                it.currentType = type
            }
        }

        if (res == null) throw IOException("${HttpErrorCode.MSG_DATA_ERROR2}  \n json = $json")
        res!!
    }
}


/**
 * 处理返回值,缓存用的
 */
@Throws(IOException::class)
fun <T> CacheEntity.handlerResult(type: Type, gson: Gson): T {
    val response = this
    val json = response.result
    return if (type === String::class.java) {
        json as T
    } else {
        var res: T? = null
        runCatching {
            if (json.isEmpty()) throw JsonSyntaxException("json length = 0")
            runCatching {
                var cls = if (type is Class<*>) type
                else (type as ParameterizedType).rawType as Class<*>
                if (IHttpResponse::class.java.isAssignableFrom(cls)) {
                    res = (cls.newInstance() as IHttpResponse).parseData(gson, json, type, null)
                }
            }.onFailure { it.printStackTrace() }
            res = res ?: gson.fromJson(json, type)
        }.onFailure { e ->
            //数据解析异常
            throw IOException("${HttpErrorCode.MSG_DATA_ERROR2} \n  原异常：$e  \n json = $json")
        }
        res.also {
            if (it is IHttpResponse) {
                it.json = json
                it.httpCode = response.code
                it.currentType = type
            }
        }
        if (res == null) throw IOException("${HttpErrorCode.MSG_DATA_ERROR2}  \n json = $json")
        res!!
    }
}